package com.xuecheng.content.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xuecheng.commons.constants.CommonConstants;
import com.xuecheng.commons.constants.CourseConstants;
import com.xuecheng.commons.enums.ErrorCode;
import com.xuecheng.commons.model.dto.BindTeachplanMediaDto;
import com.xuecheng.commons.model.dto.TeachplanDto;
import com.xuecheng.commons.model.vo.MediaVo;
import com.xuecheng.commons.model.vo.ResponseResult;
import com.xuecheng.commons.model.vo.TeachplanVo;
import com.xuecheng.commons.utils.BeanHelper;
import com.xuecheng.content.domain.CourseBase;
import com.xuecheng.content.domain.Teachplan;
import com.xuecheng.content.domain.TeachplanMedia;
import com.xuecheng.content.mappers.TeachplanMapper;
import com.xuecheng.content.service.CourseBaseService;
import com.xuecheng.content.service.TeachplanMediaService;
import com.xuecheng.content.service.TeachplanService;
import com.xuecheng.media.api.MediaClient;
import com.xuecheng.web.exceptions.BusinessException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 课程计划 服务实现类
 * </p>
 *
 * @author itheima
 * @since 2022-07-16
 */
@Service
public class TeachplanServiceImpl extends ServiceImpl<TeachplanMapper, Teachplan> implements TeachplanService {

    @Autowired
    private TeachplanMapper teachplanMapper;
    @Autowired
    private CourseBaseService courseBaseService;
    @Autowired
    private TeachplanMediaService teachplanMediaService;
    @Autowired
    private MediaClient mediaClient;

    //课程计划列表-树形结构
    @Override
    public ResponseResult treeNodes(Long courseId) {
        //1、根据课程id，一次性查询所有的课程计划数据
        List<TeachplanVo> teachplanVos = teachplanMapper.treeNodes(courseId);
        //2、提取出1级大纲，返回值
        TeachplanVo parent = teachplanVos.stream()
                .filter(vo -> vo.getGrade() == 1) //添加晒选条件
                .findFirst()
                .get();
        //3、提取2级大纲，设置到1级中
        List<TeachplanVo> twos = teachplanVos.stream()
                .filter(vo -> vo.getGrade() == 2)
                .collect(Collectors.toList());
        parent.setTeachPlanTreeNodes(twos);
        //4、循环所有的2级大纲，查询每个二级大纲下的3级
        for (TeachplanVo two : twos) {
            List<TeachplanVo> threes = teachplanVos.stream()
                    .filter(vo -> vo.getGrade() == 3
                            && vo.getParentid().equals(two.getId()))
                    .collect(Collectors.toList());
            two.setTeachPlanTreeNodes(threes);
        }
        //5、返回值
        return ResponseResult.okResult(parent);
    }

    //保存或更新
    @Override
    public ResponseResult saveOrUpdatePlan(TeachplanDto dto) {
        //1、判断课程状态，如果不是未提交或审核未通过，就报异常
        //1.1 获取课程id
        Long courseId = dto.getCourseId();
        //1.2 查询课程
        CourseBase courseBase = courseBaseService.getById(courseId);
        //1.3 判断状态
        String auditStatus = courseBase.getAuditStatus();

        if (!auditStatus.equals(CourseConstants.AUDIT_DISPAST_STATUS)
                && !auditStatus.equals(CourseConstants.AUDIT_UNPAST_STATUS)) {
            throw new BusinessException(ErrorCode.UPDATEEERROR);
        }
        //2、处理Parentid为空的情况（保存2级大纲时），查询1级大纲,赋予父级id
        if (dto.getParentid() == null) {
            LambdaQueryWrapper<Teachplan> qw = new LambdaQueryWrapper<>();
            qw.eq(Teachplan::getCourseId, courseId);
            qw.eq(Teachplan::getGrade, CourseConstants.FIRST_LEVEL);
            Teachplan parent = this.getOne(qw);
            dto.setParentid(parent.getId());
        }
        //将dto转化成java实体类
        Teachplan teachplan = BeanHelper.copyProperties(dto, Teachplan.class);

        //3、判断保存的课程计划的ID
        Boolean flag = false;
        if (teachplan.getId() == null) {
            //3.1 ID不存在，保存
            //如果是第三级计划，更新课程表的plan_num字段（作业）
            if (teachplan.getGrade() == 3) {
                LambdaUpdateWrapper<CourseBase> qw = new LambdaUpdateWrapper<>();
                qw.eq(CourseBase::getId, teachplan.getCourseId());
                qw.setSql("`plan_num`=`plan_num`+1");
                courseBaseService.update(qw);
            }
            flag = this.save(teachplan);
        } else {
            //3.2 ID存在，更新
            flag = this.updateById(teachplan);
        }

        //判断是否保存或更新成功，如果失败，报异常
        if (!flag) {
            throw new BusinessException(ErrorCode.ERROR);
        }

        return ResponseResult.okResult();
    }

    //逻辑删除
    @Override
    public ResponseResult deleteTeachplan(Long id) {
        //判断id非空
        if (id == null) {
            throw new BusinessException(ErrorCode.PARAMSERROR);
        }
        LambdaQueryWrapper<Teachplan> qw = new LambdaQueryWrapper<>();
        qw.eq(Teachplan::getStatus, CommonConstants.USING_FLAG);
        qw.eq(Teachplan::getId, id);

        boolean b = this.remove(qw);
        if (!b) {
            throw new BusinessException(ErrorCode.ERROR);
        }

        return ResponseResult.okResult();
    }

    //课程计划绑定媒资
    @Override
    public ResponseResult associateMedia(BindTeachplanMediaDto dto) {
        //1、判断基本参数
        if (dto.getTeachplanId() == null || dto.getMediaId() == null) {
            throw new BusinessException(ErrorCode.PARAMSERROR);
        }
        //2、判断课程状态
        //2.1 查询课程计划
        Teachplan teachplan = this.getById(dto.getTeachplanId());
        //2.2 根据课程计划的课程id，查询课程
        Long courseId = teachplan.getCourseId();
        CourseBase course = courseBaseService.getById(courseId);
        //2.3 判断
        String auditStatus = course.getAuditStatus();
        if (!CourseConstants.AUDIT_DISPAST_STATUS.equals(auditStatus) &&
                !CourseConstants.AUDIT_UNPAST_STATUS.equals(auditStatus)) {
            throw new BusinessException(ErrorCode.MEDIABINDERROR);
        }
        //3、调用feign接口，根据媒资id，查询媒资对象
        ResponseResult<MediaVo> result = mediaClient.findById(dto.getMediaId());
        MediaVo vo = result.getData();
        //4、查询媒资绑定数据
        LambdaQueryWrapper<TeachplanMedia> qw = new LambdaQueryWrapper<>();
        qw.eq(TeachplanMedia::getTeachplanId, dto.getTeachplanId());
        TeachplanMedia teachplanMedia = teachplanMediaService.getOne(qw);

        if (teachplanMedia == null) {
            //4.1 不存在，保存数据
            teachplanMedia = new TeachplanMedia();
            teachplanMedia.setMediaId(vo.getId());
            teachplanMedia.setMediaFilename(vo.getFilename());
            teachplanMedia.setTeachplanId(dto.getTeachplanId());
            teachplanMedia.setCourseId(courseId);
            teachplanMedia.setCreateDate(new Date());
            teachplanMediaService.save(teachplanMedia);
        } else {
            //4.2 存在，更新数据
            teachplanMedia.setMediaId(vo.getId());
            teachplanMedia.setMediaFilename(vo.getFilename());
            teachplanMediaService.updateById(teachplanMedia);
        }

        return ResponseResult.okResult();
    }
}
